package template.security;

import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;

import org.springframework.beans.factory.FactoryBean;

import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.access.intercept.DefaultFilterInvocationSecurityMetadataSource;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.security.web.access.intercept.RequestKey;
import org.springframework.security.web.util.AntUrlPathMatcher;

/**
 * 使用Hibernate的HQL从数据库中获取验证信息
 * 要注入查询权限表的HQL语句，返回的记录中应该包含两个字段，分别URL和对应的权限。
 * 
 * @author mengyang
 *
 */
public class HibernateFilterInvocationSecurityMetadataSourceFactoryBean
    extends HibernateDaoSupport implements FactoryBean<FilterInvocationSecurityMetadataSource> {
	
	//用于查询权限信息的hql语句
    private String resourceQuery;

    public boolean isSingleton() {
        return true;
    }

    public Class<FilterInvocationSecurityMetadataSource> getObjectType() {
        return FilterInvocationSecurityMetadataSource.class;
    }

    public FilterInvocationSecurityMetadataSource getObject() {
    	return new DefaultFilterInvocationSecurityMetadataSource(new AntUrlPathMatcher(), getResources());
    }
    
    protected LinkedHashMap<RequestKey, Collection<ConfigAttribute>> getResources(){
    	LinkedHashMap<RequestKey, Collection<ConfigAttribute>> resourceMap = new LinkedHashMap<RequestKey, Collection<ConfigAttribute>>();
    	
    	List<Object[]> resourceList = getHibernateTemplate().find(resourceQuery);

        for (Object[] resource : resourceList) {
            String url = (String)resource[0];
            String role = (String)resource[1];
            
            RequestKey requestKey = new RequestKey(url);
            Collection<ConfigAttribute> attributes = resourceMap.get(requestKey);
            
            if (attributes == null) {
            	attributes = new HashSet<ConfigAttribute>();
            	resourceMap.put(requestKey, attributes);
            }
            
            attributes.add(new SecurityConfig(role));
        }
    	
    	return resourceMap;
    	
    }

	public String getResourceQuery() {
		return resourceQuery;
	}

	public void setResourceQuery(String resourceQuery) {
		this.resourceQuery = resourceQuery;
	}

}